package cn.com.connext.scrm.service;

import cn.com.connext.scrm.domain.enumeration.AuditStatus;
import cn.com.connext.scrm.domain.enumeration.DeleteStatus;
import cn.com.connext.scrm.domain.master.*;
import cn.com.connext.scrm.repository.master.*;
import cn.com.connext.scrm.service.dto.JsonResult;
import cn.com.connext.scrm.service.mapper.AnswerService;
import cn.com.connext.scrm.utils.EntityUtils;
import cn.com.connext.scrm.utils.RedisUtils;
import cn.com.connext.scrm.web.rest.errors.MyErrorCode;
import cn.com.connext.scrm.web.rest.req.*;
import cn.com.connext.scrm.web.rest.resp.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.connext.common.exception.ServiceException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AnswerServiceImpl implements AnswerService {
    private final Logger log = LoggerFactory.getLogger(AnswerService.class);

    @Autowired
    private NoteRepository noteRepository;

    @Autowired
    private AuditForAnswerRepository auditForAnswerRepository;

    @Autowired
    private NoteLikesRepository noteLikesRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private BrowseRecordRepository browseRecordRepository;

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private TeacherRepository teacherRepository;

    @Autowired
    private DWAUserInfoRepository dwaUserInfoRepository;

    @Autowired
    private AnswerTypeRepository answerTypeRepository;

    @Autowired
    private NoteCollectionRepository noteCollectionRepository;

    private final static Object REDIS_LOCK3 = new Object();

    @Autowired
    private ActivityRepository activityRepository;

    @Autowired
    private WxAPIService wxAPIService;

    @Value("${login.unionid}")
    private String unionid;

    @Transactional
    @Override
    public JsonResult create(AnswerCreateReq req) {
        JsonResult jsonResult = new JsonResult();
        JSONObject content = wxAPIService.msgSafeCheck(req.getContent());
        Integer code = (Integer) content.get("errcode");
        if (code == 0) {
            Note note = new Note();
            BeanUtils.copyProperties(req, note);
            note.setCreateTime(ZonedDateTime.now());
            note.setUpdateTime(ZonedDateTime.now());
            note.setAuditStatus(AuditStatus.UNAUDITED);//审核状态
            note.setDeleteStatus(DeleteStatus.ACTIVATED);//未删除
            note.setTop(req.getTop() == null ? false : req.getTop());
            note.setRepost(false);
            note.setUserId(unionid);
            note.setNoteType(1);
            note.setAnswer(true);//true 为问答
            note.setAnswerType(req.getAnswerType());
            note.setAuditResult(0);//审核结果
            noteRepository.save(note);
            jsonResult.setState(0);
            jsonResult.setData(note);
            jsonResult.setMessage("发布成功!");
            return jsonResult;
        } else {
            jsonResult.setState(1);
            jsonResult.setMessage("内容中包含敏感词，请修改");
            return jsonResult;
        }
    }

    @Override
    public ResponseEntity<Boolean> update(AnswerUpdateReq req) {
        Note note = noteRepository.findOne(req.getId());
        if (null == note) {
            return ResponseEntity.ok(false);
        }
        BeanUtils.copyProperties(req, note);
        note.setUpdateTime(ZonedDateTime.now());
        note.setAuditStatus(AuditStatus.UNAUDITED);//审核状态
        note.setAuditResult(0);//修改还原审批状态
        noteRepository.saveAndFlush(note);
        return ResponseEntity.ok(true);
    }

    @Override
    public ResponseEntity<Boolean> delete(String req) {
        Note note = noteRepository.findOne(req);
        if (null != note) {
            note.setDeleteStatus(DeleteStatus.DELETED);
        }
        noteRepository.saveAndFlush(note);
        return ResponseEntity.ok(true);
    }

    @Override
    public ResponseEntity audit(AnswerauditReq req) {
        Note note = noteRepository.findOne(req.getId());
        if (null == note) {
            return ResponseEntity.ok(false);
        }
        //保存问答表
        note.setAuditResult(req.getAuditResult());
        if (req.getAuditResult().compareTo(1) == 0) {
            note.setAuditStatus(AuditStatus.AUDITED);
        } else {
            note.setAuditStatus(AuditStatus.UNAUDITED);
        }
        noteRepository.saveAndFlush(note);
        //保存审批记录
        AuditForAnswer auditForAnswer = new AuditForAnswer();
        auditForAnswer.setAnswertId(req.getId());
        auditForAnswer.setAuditResult(req.getAuditResult());
        auditForAnswer.setCreateTime(new Date());
        auditForAnswer.setRemark(StringUtils.isBlank(req.getRemark()) ? new String("null") : req.getRemark());
        auditForAnswerRepository.saveAndFlush(auditForAnswer);
        return ResponseEntity.ok(true);
    }

    /**
     * 内存处理 点赞数  评论数 浏览量
     */
    @Override
    public ResponseEntity<QueryAnswerByTypeResp> queryByType(AnswerQueryReq req) {
        QueryAnswerByTypeResp queryAnswerByTypeResp = new QueryAnswerByTypeResp();
        //点赞数
        List<Object[]> totalLikeList = noteLikesRepository.countAll();
        Map<String, Integer> totalLikes = covert(totalLikeList);
        //评论数
        List<Object[]> totalCommentList = commentRepository.countAll();
        Map<String, Integer> totalComments = covert(totalCommentList);
        //浏览量
        List<Object[]> totalBrowseRecordList = browseRecordRepository.countAll();
        Map<String, Integer> totalBrowseRecords = covert(totalBrowseRecordList);
        //分页查询
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "createTime"));//分页 排序
        Specification<Note> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StringUtils.isNotBlank(req.getAnswerType())) {
                list.add(criteriaBuilder.equal(root.get("answerType"), req.getAnswerType()));
            }
            if (null != req.getIsHot()) {
                list.add(criteriaBuilder.equal(root.get("isHot"), req.getIsHot()));
            }
            list.add(criteriaBuilder.equal(root.get("auditResult"), 1));
            list.add(criteriaBuilder.equal(root.get("isAnswer"), 1));
            list.add(criteriaBuilder.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED));
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page<Note> page = noteRepository.findAll(specification, pageable);
        List<Note> content = page.getContent();
        if (CollectionUtils.isEmpty(content)) {
            PageImpl<AnswerType> pageTasks = new PageImpl<>(Collections.emptyList(), pageable, page.getTotalElements());
            queryAnswerByTypeResp.setPage(pageTasks);
            queryAnswerByTypeResp.setTotalLikes(0);
            queryAnswerByTypeResp.setTotalComments(0);
            queryAnswerByTypeResp.setTotalBrowseRecords(0);
            return ResponseEntity.ok(queryAnswerByTypeResp);
        }
        List<QueryByTypeResp> queryByTypeRespList = EntityUtils.dtoList2PojoList(content, QueryByTypeResp.class);
        queryByTypeRespList.forEach(c -> {
            c.setTotalBrowseRecords(totalBrowseRecords.get(c.getId()) == null ? new Integer(0) : totalBrowseRecords.get(c.getId()));//浏览量
            c.setTotalComments(totalComments.get(c.getId()) == null ? new Integer(0) : totalComments.get(c.getId()));//评论数
            c.setTotalLikes(totalLikes.get(c.getId()) == null ? new Integer(0) : totalLikes.get(c.getId()));//点赞数
        });
        //问答分类点赞数 =每个问答点赞数之和 +问答分类的点赞数
        Integer likeCountForType = totalLikes.get(req.getAnswerType()) == null ? new Integer(0) : totalLikes.get(req.getAnswerType());
        Integer likeCount = queryByTypeRespList.stream().mapToInt(QueryByTypeResp::getTotalLikes).sum() + likeCountForType;
        //问答分类浏览量 =每个问答浏览量之和 +问答分类的浏览量
        Integer browseRecordForType = totalBrowseRecords.get(req.getAnswerType()) == null ? new Integer(0) : totalLikes.get(req.getAnswerType());
        Integer browseRecordCount = queryByTypeRespList.stream().mapToInt(QueryByTypeResp::getTotalBrowseRecords).sum() + browseRecordForType;
        //问答分类评论数 =每个问答评论数之和
        Integer commentCount = queryByTypeRespList.stream().mapToInt(QueryByTypeResp::getTotalComments).sum();
        PageImpl pageImpl = new PageImpl<>(queryByTypeRespList, pageable, page.getTotalElements());
        queryAnswerByTypeResp.setPage(pageImpl);
        queryAnswerByTypeResp.setTotalLikes(likeCount);
        queryAnswerByTypeResp.setTotalComments(commentCount);
        queryAnswerByTypeResp.setTotalBrowseRecords(browseRecordCount);
        //分类详情
        if (StringUtils.isNotBlank(req.getAnswerType())) {
            QueryAnswerTypeResp queryAnswerTypeResp = new QueryAnswerTypeResp();
            AnswerType answerType = answerTypeRepository.findOne(req.getAnswerType());
            if (null != answerType) {
                BeanUtils.copyProperties(answerType, queryAnswerTypeResp);
                queryAnswerByTypeResp.setQueryAnswerTypeResp(queryAnswerTypeResp);
            }
        }
        return ResponseEntity.ok(queryAnswerByTypeResp);
    }

    @Override
    public ResponseEntity<List<QueryAnswerDetailResp>> otherAnswer() {
        //查询非热门活动
        List<Note> notes = noteRepository.findOtherAnswer();
        if (CollectionUtils.isEmpty(notes)) {
            return ResponseEntity.ok(Collections.emptyList());
        }
        List<QueryAnswerDetailResp> queryAnswerDetailResps = EntityUtils.dtoList2PojoList(notes, QueryAnswerDetailResp.class);
        return ResponseEntity.ok(queryAnswerDetailResps);
    }

    @Override
    public ResponseEntity<List<QueryAnswerDetailResp>> hotAnswer(DeleteReq req) {
        List<Note> notes = noteRepository.findHotAnswer();
        if (CollectionUtils.isEmpty(notes)) {
            return ResponseEntity.ok(Collections.emptyList());
        }
        List<QueryAnswerDetailResp> queryAnswerDetailResps = EntityUtils.dtoList2PojoList(notes, QueryAnswerDetailResp.class);
        if (CollectionUtils.isNotEmpty(queryAnswerDetailResps)) {
            queryAnswerDetailResps.forEach(c -> {
                //浏览量
                Integer totalBrowseRecords = 0;
                totalBrowseRecords = browseRecordRepository.countAllByNoteId(c.getId());
                c.setTotalBrowseRecords(totalBrowseRecords);
            });
        }
        if (StringUtils.isNotBlank(req.getId())){
            return ResponseEntity.ok(queryAnswerDetailResps.stream().filter(e->e.getId().compareTo(req.getId())!=0).collect(Collectors.toList()));
        }
        return ResponseEntity.ok(queryAnswerDetailResps);
    }

    @Override
    public ResponseEntity manageQuery(ManageQueryReq req) {
        //分页查询
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "createTime"));//分页 排序
        Specification<Note> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StringUtils.isNotBlank(req.getAnswerType())) {
                list.add(criteriaBuilder.equal(root.get("answerType"), req.getAnswerType()));
            }
            if (StringUtils.isNotEmpty(req.getContent())) {
                list.add(criteriaBuilder.like(root.get("content"), "%" + req.getContent() + "%"));
            }
            if (req.getAuditResult() != null) {
                list.add(criteriaBuilder.equal(root.get("auditResult"), req.getAuditResult()));
            }
            list.add(criteriaBuilder.equal(root.get("isAnswer"), 1));
            list.add(criteriaBuilder.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED));
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page<Note> page = noteRepository.findAll(specification, pageable);
        List<Note> content = page.getContent();
        if (CollectionUtils.isEmpty(content)) {
            PageImpl<AnswerType> pageTasks = new PageImpl<>(Collections.emptyList(), pageable, page.getTotalElements());
            return ResponseEntity.ok(pageTasks);
        }
        List<QueryForManageResp> queryForManageResps = EntityUtils.dtoList2PojoList(content, QueryForManageResp.class);
        queryForManageResps.forEach(c -> {
            //发帖人昵称、头像、标签
            Member member = memberRepository.findOneByUnionId(c.getUserId());
            if (null != member) {
                c.setNickName(member.getNickName());
            }
            //点赞数
            Integer totalLikes = 0;
            //评论数
            Integer totalComments = 0;
            //收藏数
            Integer totalCollection = 0;
            //浏览量
            Integer totalBrowseRecords = 0;
            totalLikes = noteLikesRepository.countAllByNoteId(c.getId());
            totalComments = commentRepository.countAllByNoteId(c.getId());
            totalBrowseRecords = browseRecordRepository.countAllByNoteId(c.getId());
            totalCollection = noteCollectionRepository.countAllByNoteId(c.getId());
            c.setTotalLikes(totalLikes);
            c.setTotalComments(totalComments);
            c.setTotalBrowseRecords(totalBrowseRecords);
            c.setTotalCollection(totalCollection);
            AnswerType answerType = answerTypeRepository.findOne(c.getAnswerType());
            c.setAnswerTypeTitle(answerType.getTitle());
        });
        return ResponseEntity.ok(new PageImpl<>(queryForManageResps, pageable, page.getTotalElements()));
    }

    @Override
    public ResponseEntity<Page> queryByActId(QueryByActIdReq req) {
        Activity activity = activityRepository.findOne(req.getId());
        if (null == activity) {
            return null;
        }
        //分页查询
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "createTime"));//分页 排序
        Specification<Note> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.between(root.get("createTime"), activity.getStartTime(), activity.getEndTime()));
            list.add(criteriaBuilder.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED));
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page<Note> page = noteRepository.findAll(specification, pageable);
        List<Note> content = page.getContent();
        if (CollectionUtils.isEmpty(content)) {
            PageImpl<AnswerType> pageTasks = new PageImpl<>(Collections.emptyList(), pageable, page.getTotalElements());
            return ResponseEntity.ok(pageTasks);
        }
        List<QueryForManageResp> queryForManageResps = EntityUtils.dtoList2PojoList(content, QueryForManageResp.class);
        queryForManageResps.forEach(c -> {
            //发帖人昵称、头像、标签
            Member member = memberRepository.findOneByUnionId(c.getUserId());
            if (null != member) {
                c.setNickName(member.getNickName());
            }
            //点赞数
            Integer totalLikes = 0;
            //评论数
            Integer totalComments = 0;
            //收藏数
            Integer totalCollection = 0;
            //浏览量
            Integer totalBrowseRecords = 0;
            totalLikes = noteLikesRepository.countAllByNoteId(c.getId());
            totalComments = commentRepository.countAllByNoteId(c.getId());
            totalBrowseRecords = browseRecordRepository.countAllByNoteId(c.getId());
            totalCollection = noteCollectionRepository.countAllByNoteId(c.getId());
            c.setTotalLikes(totalLikes);
            c.setTotalComments(totalComments);
            c.setTotalBrowseRecords(totalBrowseRecords);
            c.setTotalCollection(totalCollection);
        });
        return ResponseEntity.ok(new PageImpl<>(queryForManageResps, pageable, page.getTotalElements()));
    }

    @Override
    public void setIsTop(String id) {
        Note note = noteRepository.findOne(id);
        if (note == null) {
            throw new ServiceException(MyErrorCode.ERROR_DATA_ISNULL);
        }
        Note result = new Note();
        BeanUtils.copyProperties(note, result);
        if (result.getTop()) {
            result.setTop(false);
            result.setUpdateTime(ZonedDateTime.now());
        } else {
            result.setTop(true);
            result.setUpdateTime(ZonedDateTime.now());
        }
        noteRepository.saveAndFlush(result);
    }


    @Override
    public void setIsHot(String id) {
        Note note = noteRepository.findOne(id);
        if (note == null) {
            throw new ServiceException(MyErrorCode.ERROR_DATA_ISNULL);
        }
        Note result = new Note();
        BeanUtils.copyProperties(note, result);
        if (result.getHot()) {
            result.setHot(false);
            result.setUpdateTime(ZonedDateTime.now());
        } else {
            result.setHot(true);
            result.setUpdateTime(ZonedDateTime.now());
        }
        noteRepository.saveAndFlush(result);
    }

    @Override
    public ResponseEntity<QueryAnswerDetailForManageResp> detail(String req) {
        QueryAnswerDetailForManageResp queryAnswerDetailResp = new QueryAnswerDetailForManageResp();
        Note note = noteRepository.findOne(req);
        if (null == note) {
            return ResponseEntity.ok(queryAnswerDetailResp);
        }
        BeanUtils.copyProperties(note, queryAnswerDetailResp);
        //发帖人昵称、头像、标签
        AnswerType answerType = answerTypeRepository.findOne(note.getAnswerType());
        if (null == answerType) {
            return ResponseEntity.ok(queryAnswerDetailResp);
        }
        queryAnswerDetailResp.setAnswerTypeTitle(answerType.getTitle());
        if (StringUtils.isNotEmpty(note.getUserId())) {
            Member member = memberRepository.findOneByUnionId(note.getUserId());
            if (null != member) {
                queryAnswerDetailResp.setNickName(member.getNickName());
                queryAnswerDetailResp.setHeadImgUrl(member.getHeadImgUrl());
                if (org.apache.commons.lang3.StringUtils.isNotEmpty(member.getMobile())) {
                    String mobile = member.getMobile();
                    JSONArray tagsArray = new JSONArray();
//                        tagsList.add("官方认证");
                    if (null != member.getOfficialCertification() && member.getOfficialCertification() == true) {
                        JSONObject tag = new JSONObject();
                        tag.put("kind", 2);
                        tag.put("text", "官方认证");
                        tagsArray.add(tag);
                    } else {
                        List<String> teacherMobiles = getTeacherMobileList();
                        if (teacherMobiles.contains(mobile)) {
                            JSONObject tag = new JSONObject();
                            tag.put("kind", 1);
                            tag.put("text", "DWA导师");
                            tagsArray.add(tag);
                        } else {
                            List<DwaUserInfo> dwaUserInfos = dwaUserInfoRepository.findByUnionIdOrderByLessonLevelDesc(note.getUserId());
                            if (null != dwaUserInfos && dwaUserInfos.size() > 0) {
                                //dwa学员标签
                                DwaUserInfo dwaUserInfo = dwaUserInfos.get(0);
                                if (org.apache.commons.lang3.StringUtils.isNotEmpty(dwaUserInfo.getLessonLevel())) {
                                    String level = dwaUserInfo.getLessonLevel();
                                    JSONObject tag = new JSONObject();
                                    tag.put("kind", 0);
                                    if ("LEVEL1".equals(level)) {
                                        tag.put("text", "DWA L1");
                                    } else if ("LEVEL2".equals(level)) {
                                        tag.put("text", "DWA L2");
                                    } else if ("LEVEL3".equals(level)) {
                                        tag.put("text", "DWA L3");
                                    } else {
                                        tag.put("text", "DWA");
                                    }
                                    tagsArray.add(tag);
                                }
                            }
                        }
                    }
                    queryAnswerDetailResp.setUserTagList(tagsArray);
                }
            }
        }
        //点赞数
        Integer totalLikes = 0;
        //评论数
        Integer totalComments = 0;
        //收藏数
        Integer totalCollection = 0;
        //浏览量
        Integer totalBrowseRecords = 0;
        totalLikes = noteLikesRepository.countAllByNoteId(req);
        totalComments = commentRepository.countAllByNoteId(req);
        totalBrowseRecords = browseRecordRepository.countAllByNoteId(req);
        totalCollection = noteCollectionRepository.countAllByNoteId(req);
        queryAnswerDetailResp.setTotalLikes(totalLikes);
        queryAnswerDetailResp.setTotalComments(totalComments);
        queryAnswerDetailResp.setTotalBrowseRecords(totalBrowseRecords);
        queryAnswerDetailResp.setTotalCollection(totalCollection);
        return ResponseEntity.ok(queryAnswerDetailResp);
    }


    /**
     * 数据转换
     */
    private Map<String, Integer> covert(List<Object[]> content) {
        if (CollectionUtils.isEmpty(content)) {
            return Collections.emptyMap();
        }
        Map<String, Integer> result = new HashMap<>();
        content.forEach(c -> {
            List<Object> list = Arrays.asList(c);
            result.put(list.get(0).toString(), Integer.valueOf(list.get(1).toString()));
        });
        return result;
    }

    private List<String> getTeacherMobileList() {
        List<String> result = null;
        String redisKey = "TeacherMobileList";
        Object banners = redisUtils.get(redisKey);
        if (banners != null && banners instanceof List) {
            result = (List<String>) banners;
        }
        if (result == null) {
            synchronized (REDIS_LOCK3) {
                result = teacherRepository.findAllMobile();
                if (result == null) {
                    result = new ArrayList<>();
                }
                redisUtils.set(redisKey, result, 1200L);
            }
        }
        return result;
    }
}
